#ifndef __M_QUEUE_H__
#define __M_QUEUE_H__
#include"../mqcommon/mq_helper.hpp"
#include"../mqcommon/mq_logger.hpp"
#include"../mqcommon/mq_msg.pb.h"
#include<unordered_map>
#include <google/protobuf/map.h>
#include<vector>
#include<string>
#include<iostream>
namespace bitmq{
//1、定义一个队列数据类
class MessageQueue{
    public:
    using ptr=std::shared_ptr<MessageQueue>;
    std::string _name;
    bool _durable;
    bool _exclusive;
    bool _auto_delete;
    google::protobuf::Map<std::string, std::string> _args;
    MessageQueue(){}
    MessageQueue(std::string name,bool durable,bool exclusive,bool auto_delete,const google::protobuf::Map<std::string, std::string>& args):
    _name(name),
    _durable(durable),
    _exclusive(exclusive),
    _auto_delete(auto_delete),
    _args(args){}
    void setArgs(const std::string&str_args)//将数据存入sqlite的格式  k1=v1&k2=v2&
    {
        std::vector<std::string> kvs;
        bitmq::StrHelper::split(str_args,"&",kvs);
        for(auto&e:kvs)
        {
            size_t pos=e.find('=');
            std::string key=e.substr(0,pos);
            std::string value=e.substr(pos+1);
            _args[key]=value;
        }
    }
    std::string getArgs()
    {
        std::string str;
        auto it=_args.begin();
        for(;it!=_args.end();it++)
        {
            str+=it->first+"="+it->second+"&";
        }
        return str;
    }
};
//2、定义一个持久化数据管理类
using MsgQueueMap=std::unordered_map<std::string,MessageQueue::ptr>;
class MessageQueueMap{
    public:
    MessageQueueMap(const std::string&dbfile):_db(dbfile){
        std::string path=bitmq::FileHelper::parentDirectory(dbfile);
        bitmq::FileHelper::createDirectory(path);
        assert(_db.open());
        createTable();
    }
    //创建消息队列数据表
    void createTable()
    {
        //create table if not exists queue_table values(name varchar(32) primary key,durable int,exclusive int,auto_delate,args varchar(128);)
        std::stringstream ss;
        ss<<"create table if not exists queue_table(name varchar(32) primary key,";
        ss<<"durable int,";
        ss<<"exclusive int,";
        ss<<"auto_delate,";
        ss<<"args varchar(128));";
        bool ret=_db.exec(ss.str(),nullptr,nullptr);
        if(!ret)
        {
            ELOG("创建队列持久化数据表失败!");
            abort();
        }
    }
    //删除消息队列数据表
    void removetable()
    {
        #define REMOVETABLE "drop table if exists queue_table"

        bool ret=_db.exec(REMOVETABLE,nullptr,nullptr);
        if(!ret)
        {
            ELOG("删除队列持久化表失败！");
        }
    }
    //向队列数据表插入数据
    bool insert(MessageQueue::ptr queue)
    {
        std::stringstream ss;
        ss<<"insert into queue_table values(";
        ss<<"'"<<queue->_name<<"',";
        ss<<queue->_durable<<",";
        ss<<queue->_exclusive<<",";
        ss<<queue->_auto_delete<<",";
        ss<<"'"<<queue->getArgs()<<"');";

        bool ret=_db.exec(ss.str(),nullptr,nullptr);
        if(!ret)
        {
            ELOG("向队列数据表插入数据失败!");
            return false;
        }
        return true;
    }
    //移除数据表的数据
    void remove(const std::string& name)
    {
        std::stringstream ss;
        ss<<"delete from queue_table where name=";
        ss<<"'"<<name<<"';";
        _db.exec(ss.str(),nullptr,nullptr);
    }
    //获取和恢复队列数据
    MsgQueueMap recovery()
    {
        MsgQueueMap result;
        std::string sql="select name,durable,exclusive,auto_delate,args from queue_table;";
        _db.exec(sql,selectCallback,&result);
        return result;
    }
    private:
    static int selectCallback(void*arg,int col,char**row,char**fileds)
    {
        MsgQueueMap*map=(MsgQueueMap*)arg;
        auto msgq=std::make_shared<MessageQueue>();//在这里用的无参构造
        msgq->_name=row[0];
        msgq->_durable=(bool)std::stoi(row[1]);
        msgq->_exclusive=(bool)std::stoi(row[2]);
        msgq->_auto_delete=(bool)std::stoi(row[3]);
        msgq->setArgs(row[4]);
        map->insert(std::make_pair(msgq->_name,msgq));
        return 0;
    }
    bitmq::Sqlite _db;
};



//3、定义一个队列内存管理类--对外提供接口
class MsgqueueManager{
    public:
    using ptr=std::shared_ptr<MsgqueueManager>;
    MsgqueueManager(std::string dbfile):_msg_qmap(dbfile){
        _msg_queues=_msg_qmap.recovery();//恢复在sqlite数据库中的数据
    }
    //声明队列
    bool declareQueue(const std::string name,
        bool durable,
        bool exclusive,
        bool auto_delete,
        const google::protobuf::Map<std::string, std::string>& args)
        {
            std::unique_lock<std::mutex> lock(_mutex);
            auto it=_msg_queues.find(name);
            if(it!=_msg_queues.end())//找到了，不需要添加
            {
                return true;
            }
            MessageQueue::ptr mq=std::make_shared<MessageQueue>();
            mq->_name=name;
            mq->_durable=durable;
            mq->_exclusive=exclusive;
            mq->_auto_delete=auto_delete;
            mq->_args=args;

            if(mq->_durable==true)
            {
                bool ret=_msg_qmap.insert(mq);//给数据库来一份
                if(!ret) return false;
            }
            _msg_queues.insert(std::make_pair(mq->_name,mq));
            return true;
        }
    //移除队列
    void remove(const std::string name)
    {
        std::unique_lock<std::mutex> lock(_mutex);
        auto it=_msg_queues.find(name);
        if(it==_msg_queues.end())//找到了，不需要添加
        {
            return;
        }
        if(it->second->_durable==true)
        _msg_qmap.remove(name);
        _msg_queues.erase(name);
    }
    //获取指定队列
    MessageQueue::ptr selectQueue(const std::string name)
    {
        std::unique_lock<std::mutex> lock(_mutex);
        auto it=_msg_queues.find(name);
        if(it==_msg_queues.end())//找到了，不需要添加
        {
            return MessageQueue::ptr(); 
        }
        return it->second;
    }
    //获取所有消息队列
    MsgQueueMap getall()
    {
        std::unique_lock<std::mutex> lock(_mutex);
        return _msg_queues;
    }

    bool exists(const std::string name)
    {
        std::unique_lock<std::mutex> lock(_mutex);
        auto it=_msg_queues.find(name);
        if(it!=_msg_queues.end())//找到了
        {
            return true; 
        }
        return false;
    }
    //获取队列个数
    size_t size()
    {
        std::unique_lock<std::mutex> lock(_mutex);
        return _msg_queues.size();
    }
    //清除所有队列数据
    void clear()
    {
        std::unique_lock<std::mutex> lock(_mutex);
        _msg_qmap.removetable();
        _msg_queues.clear();
    }
    private:
    std::mutex _mutex;
    MessageQueueMap _msg_qmap;
    MsgQueueMap _msg_queues;
};
}
#endif